﻿/*=============================================================================
* File Name : Matrix4.h                         Ver : 1.00  Date : 2009-3-30
*
* Description :
*
*       ４行４列座標変換行列計算　ヘッダ
*
* Author : 土田　悠貴.
*============================================================================*/
#ifndef _MATRIX4_H_
#define _MATRIX4_H_
namespace tglib
{

class Vector2;
class Vector3;
class Vector4;
class Plane;
class Quaternion;
class Matrix3;

/**
 * @brief 4行4列の行列計算クラス.
 */
class Matrix4
{
public:
	/*===========================================================================*/
	/**
	 * コンストラクタ．
	 */
	Matrix4();

	/*===========================================================================*/
	/**
	 * コンストラクタ．
	 *
	 * @param [in]     m11～m44　行列の各成分．
	 */
	Matrix4( float m11, float m12, float m13, float m14,
			   float m21, float m22, float m23, float m24,
			   float m31, float m32, float m33, float m34,
			   float m41, float m42, float m43, float m44 );

	/*===========================================================================*/
	/**
	 * コンストラクタ．
	 *
	 * @param [in]     axisX　	X軸の成分．
	 * @param [in]     axisY　	Y軸の成分．
	 * @param [in]     axisZ　	Z軸の成分．
	 * @param [in]     position　座標の成分．
	 */
	Matrix4( const Vector4& axisX,
			 const Vector4& axisY,
			 const Vector4& axisZ,
			 const Vector4& position );

	/*===========================================================================*/
	/**
	 * コンストラクタ．
	 *
	 * @param [in]    p　行列の各成分．
	 */
	Matrix4( const float* p );

	/*===========================================================================*/
	/**
	 * コンストラクタ．
	 *
	 * @param [in]    M　3行3列行列．
	 */
	Matrix4( const Matrix3& M );

	/*===========================================================================*/
	/**
	 * コンストラクタ．
	 *
	 * @param [in]    q　クォータニオン．
	 */
	Matrix4( const Quaternion& q );

	/*===========================================================================*/
	/**
	 * 単位行列化する．
	 *
	 * @return   単位行列 ．
	 */
	Matrix4& identity();

	/*===========================================================================*/
	/**
	 * 拡大縮小行列を乗算．
	 *
	 * @param [in]     x x成分 ．
	 * @param [in]     y y成分 ．
	 * @param [in]     z z成分 ．
	 * @return   乗算した行列 ．
	 */
	Matrix4& scale( float x, float y, float z );

	/*===========================================================================*/
	/**
	 * 拡大縮小行列を乗算．
	 *
	 * @param [in]     scaleFactor xyz成分 ．
	 * @return   乗算した行列 ．
	 */
	Matrix4& scale( const Vector3& scaleFactor );

	/*===========================================================================*/
	/**
	 * 拡大縮小行列を乗算．
	 *
	 * @param [in]     scaleFactor xyz成分 ．
	 * @return   乗算した行列 ．
	 */
	Matrix4& scale( float scaleFactor );

	/*===========================================================================*/
	/**
	 * 回転行列を乗算．
	 *
	 * @param [in]     angle 回転角度 ．
	 * @param [in]     axisX ｘ軸成分．
	 * @param [in]     axisY ｙ軸成分 ．
	 * @param [in]     axisZ ｚ軸成分 ．
	 * @return   乗算した行列 ．
	 */
	Matrix4& rotate( float angle, float axisX, float axisY, float axisZ );
	
	/*===========================================================================*/
	/**
	 * 回転行列を乗算．
	 *
	 * @param [in]     angle 回転角度 ．
	 * @param [in]     axis xyz軸成分．
	 * @return   乗算した行列 ．
	 */
	Matrix4& rotate( float angle, const Vector3& axis );
	
	/*===========================================================================*/
	/**
	 * 回転行列を乗算．
	 *
	 * @param [in]     q クォータニオン ．
	 * @return   乗算した行列 ．
	 */
	Matrix4& rotate( const Quaternion& q );

	/*===========================================================================*/
	/**
	 * x軸の回転行列を乗算．
	 *
	 * @param [in]     x 角度．
	 * @return   乗算した行列 ．
	 */
	Matrix4& rotateX( float angle );

	/*===========================================================================*/
	/**
	 * y軸の回転行列を乗算．
	 *
	 * @param [in]     y 角度 ．
	 * @return   乗算した行列 ．
	 */
	Matrix4& rotateY( float angle );

	/*===========================================================================*/
	/**
	 * z軸の回転行列を乗算．
	 *
	 * @param [in]     z 角度 ．
	 * @return   乗算した行列 ．
	 */
	Matrix4& rotateZ( float angle );
	
	/*===========================================================================*/
	/**
	 * ヨー、ピッチ、ロールの回転行列を乗算．
	 *
	 * @param [in]     yaw   ヨー．
	 * @param [in]     pitch ピッチ．
	 * @param [in]     roll  ロール．
	 * @return   乗算した行列 ．
	 */
	Matrix4& rotateYawPitchRoll( float yaw, float pitch, float roll );

	/*===========================================================================*/
	/**
	 * 平行移動を乗算．
	 *
	 * @param [in]     x x座標．
	 * @param [in]     y y座標．
	 * @param [in]     z z座標．
	 * @return   乗算した行列 ．
	 */
	Matrix4& translate( float x, float y, float z );

	/*===========================================================================*/
	/**
	 * 平行移動を乗算．
	 *
	 * @param [in]     translation 三次元座標．
	 * @return   乗算した行列 ．
	 */
	Matrix4& translate( const Vector3& translation );

	/*===========================================================================*/
	/**
	 * 逆行列にする．
	 *
	 * @return   変換した行列 ．
	 */
	Matrix4& inverse();

	/*===========================================================================*/
	/**
	 * 逆行列にする．
	 *
	 * @return   変換した行列 ．
	 */
	Matrix4& inverseFast();

	/*===========================================================================*/
	/**
	 * 転置行列にする．
	 *
	 * @return   変換した行列 ．
	 */
	Matrix4& transpose();

	/*===========================================================================*/
	/**
	 * 転置逆行列にする．
	 *
	 * @return   変換した行列 ．
	 */
	Matrix4& inverseTranspose();

	/*===========================================================================*/
	/**
	 * 逆行列を取得する．
	 *
	 * @return   逆行列．
	 */
	Matrix4 getInverse() const;

	/*===========================================================================*/
	/**
	 * 逆行列を取得する．
	 *
	 * @return   逆行列．
	 */
	Matrix4 getInverseFast() const;

	/*===========================================================================*/
	/**
	 * 転置行列を取得する．
	 *
	 * @return   転置行列．
	 */
	Matrix4 getTranspose() const;

	/*===========================================================================*/
	/**
	 * 転置逆行列を取得する．
	 *
	 * @return   転置逆行列．
	 */
	Matrix4 getInverseTranspose() const;

	/*===========================================================================*/
	/**
	 * スケール値の設定．
	 *
	 * @param [in]     x x成分 ．
	 * @param [in]     y y成分 ．
	 * @param [in]     z z成分 ．
	 * @return   設定した行列 ．
	 */
	Matrix4& setScale( float x, float y, float z );

	/*===========================================================================*/
	/**
	 * スケール値の設定．
	 *
	 * @param [in]     scaleFactor xyz成分 ．
	 * @return   設定した行列 ．
	 */
	Matrix4& setScale( const Vector3& scaleFactor );

	/*===========================================================================*/
	/**
	 * スケール値の設定．
	 *
	 * @param [in]     scaleFactor xyz成分 ．
	 * @return   設定した行列 ．
	 */
	Matrix4& setScale( float scaleFactor );

	/*===========================================================================*/
	/**
	 * 回転行列の設定．
	 *
	 * @param [in]     angle 角度．
	 * @param [in]     axisX x軸 ．
	 * @param [in]     axisY y軸 ．
	 * @param [in]     axisZ z軸 ．
	 * @return   設定した行列 ．
	 */
	Matrix4& setRotation( float angle, float axisX, float axisY, float axisZ );
	
	/*===========================================================================*/
	/**
	 * 回転行列の設定．
	 *
	 * @param [in]     angle 角度．
	 * @param [in]     axis  xyz軸 ．
	 * @return   設定した行列 ．
	 */
	Matrix4& setRotation( float angle, const Vector3& axis );

	/*===========================================================================*/
	/**
	 * 回転行列の設定．
	 *
	 * @param [in]     q クォータニオン．
	 * @return   設定した行列 ．
	 */
	Matrix4& setRotation( const Quaternion& q );

	/*===========================================================================*/
	/**
	 * X軸の回転行列の設定．
	 *
	 * @param [in]     angle 角度．
	 * @return   設定した行列 ．
	 */
	Matrix4& setRotationX( float angle );

	/*===========================================================================*/
	/**
	 * Y軸の回転行列の設定．
	 *
	 * @param [in]     angle 角度．
	 * @return   設定した行列 ．
	 */
	Matrix4& setRotationY( float angle );

	/*===========================================================================*/
	/**
	 * Z軸の回転行列の設定．
	 *
	 * @param [in]     angle 角度．
	 * @return   設定した行列 ．
	 */
	Matrix4& setRotationZ( float angle );

	/*===========================================================================*/
	/**
	 * ロール、ピッチ、ヨーから回転行列の設定．
	 *
	 * @param [in]     angle 角度．
	 * @param [in]     angle 角度．
	 * @param [in]     angle 角度．
	 * @return   設定した行列 ．
	 */
	Matrix4& setRotationYawPitchRoll( float yaw, float pitch, float roll );

	/*===========================================================================*/
	/**
	 * 平行移動量の設定．
	 *
	 * @param [in]     x x座標．
	 * @param [in]     y y座標．
	 * @return   設定した行列 ．
	 */
	Matrix4& setTranslation( float x, float y, float z );

	/*===========================================================================*/
	/**
	 * 平行移動量の設定．
	 *
	 * @param [in]     translation 三次元座標．
	 * @return   設定した行列 ．
	 */
	Matrix4& setTranslation( const Vector3& translation );

	/*===========================================================================*/
	/**
	 * 右手座標系透視変換行列の設定．
	 *
	 * @param [in] fov	 視野角．
	 * @param [in] aspect アスペクト比．
	 * @param [in] near	 近グリップ．
	 * @param [in] far	 遠グリップ．
	 * @return   設定した行列 ．
	 */
	Matrix4& setPerspective( float fov, float aspect, float near, float far );

	/*===========================================================================*/
	/**
	 * 右手座標系正射影変換行列の設定．
	 *
	 * @param [in] left	 クリップ面の左側の座標．
	 * @param [in] right	 クリップ面の右側の座標．
	 * @param [in] bottom クリップ面の下側の座標．
	 * @param [in] top	 クリップ面の上側の座標．
	 * @param [in] near	 近グリップ．
	 * @param [in] far	 遠グリップ．
	 * @return   設定した行列 ．
	 */
	Matrix4& setOrtho( float left, float right, float bottom, float top, float near = -1.0f, float far = 1.0f );
	
	/*===========================================================================*/
	/**
	 * 右手座標系視野変換行列の設定．
	 *
	 * @param [in] eyeX	 視点の位置(X座標)．
	 * @param [in] eyeY	 視点の位置(Y座標)．
	 * @param [in] eyeZ	 視点の位置(Z座標)．
	 * @param [in] atX	 注視点(X座標)．
	 * @param [in] atX	 注視点(Y座標)．
	 * @param [in] atX	 注視点(Z座標)．
	 * @param [in] upX	 上方向のベクトル(X座標)．
	 * @param [in] upX	 上方向のベクトル(Y座標)．
	 * @param [in] upX	 上方向のベクトル(Z座標)．
	 * @return   設定した行列 ．
	 */
	Matrix4& setLookAt( float eyeX, float eyeY, float eyeZ,
						  float atX,  float atY,  float atZ,
						  float upX,  float upY,  float upZ    );

	/*===========================================================================*/
	/**
	 * 右手座標系視野変換行列の設定．
	 *
	 * @param [in] eye	 視点の位置．
	 * @param [in] at	 注視点．
	 * @param [in] up	 上方向のベクトル．
	 * @return   設定した行列 ．
	 */
	Matrix4& setLookAt( const Vector3& eye, const Vector3& at, const Vector3& up );
	
	/*===========================================================================*/
	/**
	 * 座標変換．
	 *
	 * @param [in]     v 三次元座標．
	 * @return   変換した三次元座標．
	 */
	Vector3 transform( const Vector3& v ) const;

	/*===========================================================================*/
	/**
	 * 座標変換．
	 *
	 * @param [in]     v 三次元座標．
	 * @return   変換した三次元座標．
	 */
	Vector3 transformCoord( const Vector3& v ) const;

	/*===========================================================================*/
	/**
	 * 座標変換(法線ベクトル用)．
	 *
	 * @param [in]     v 三次元座標．
	 * @return   変換した三次元座標．
	 */
	Vector3 transformNormal( const Vector3& v ) const;

	/*===========================================================================*/
	/**
	 * 軸、位置の設定．
	 *
	 * @param [in]     axisX x軸の位置．
	 * @return   設定した行列．
	 */
	Matrix4& setAxisX( const Vector3& axisX );

	/*===========================================================================*/
	/**
	 * 軸、位置の設定．
	 *
	 * @param [in]     axisY y軸の位置．
	 * @return   設定した行列．
	 */
	Matrix4& setAxisY( const Vector3& axisY );

	/*===========================================================================*/
	/**
	 * 軸、位置の設定．
	 *
	 * @param [in]     axisZ z軸の位置．
	 * @return   設定した行列．
	 */
	Matrix4& setAxisZ( const Vector3& axisZ );

	/*===========================================================================*/
	/**
	 * 軸、位置の設定．
	 *
	 * @param [in]     position 座標の位置．
	 * @return   設定した行列．
	 */
	Matrix4& setPosition( const Vector3& position );

	/*===========================================================================*/
	/**
	 * ロールの取得．
	 *
	 * @return   ロール．
	 */
	float getRoll() const;

	/*===========================================================================*/
	/**
	 * ピッチの取得．
	 *
	 * @return   ピッチ．
	 */
	float getPitch() const;

	/*===========================================================================*/
	/**
	 * ヨーの取得．
	 *
	 * @return   ヨー．
	 */
	float getYaw() const;

	/*===========================================================================*/
	/**
	 * クォータニオンを取得．
	 *
	 * @return   クォータニオン．
	 */
	Quaternion getQuaternion() const;

	/*===========================================================================*/
	/**
	 * 軸、位置の取得．
	 *
	 * @return   X軸．
	 */
	Vector3 getAxisX() const;

	/*===========================================================================*/
	/**
	 * 軸、位置の取得．
	 *
	 * @return   Y軸．
	 */
	Vector3 getAxisY() const;

	/*===========================================================================*/
	/**
	 * 軸、位置の取得．
	 *
	 * @return   Z軸．
	 */
	Vector3 getAxisZ() const;

	/*===========================================================================*/
	/**
	 * 軸、位置の取得．
	 *
	 * @return   座標．
	 */
	Vector3 getPosition() const;

	/*===========================================================================*/
	/**
	 * (float*型)キャスト演算子オーバーロード．
	 *
	 * @return   型変換をした行列成分．
	 */
	operator float* ();

	/*===========================================================================*/
	/**
	 * (const flost*型)キャスト演算子オーバーロード．
	 *
	 * @return   型変換をした行列成分．
	 */
	operator const float* ();

	/*===========================================================================*/
	/**
	 * (+)単項演算子オーバーロード．
	 *
	 * @return 結果のMatrix4．
	 */
	Matrix4 operator + () const;

	/*===========================================================================*/
	/**
	 * (-)単項演算子オーバーロード．
	 *
	 * @return 結果のMatrix4.
	 */
	Matrix4 operator - () const;

	/*===========================================================================*/
	/**
	 * (+=) 演算子オーバーロード．
	 * 
	 * @param [in]  M Matrix4．
	 * @return 結果のMatrix4．
	 */
	Matrix4 operator += ( const Matrix4& M );

	/*===========================================================================*/
	/**
	 * (-=) 演算子オーバーロード．
	 * 
	 * @param [in]  M Matrix4．
	 * @return 結果のMatrix4．
	 */
	Matrix4 operator -= ( const Matrix4& M );

	/*===========================================================================*/
	/**
	 * (*=) 演算子オーバーロード．
	 * 
	 * @param [in]  M Matrix4．
	 * @return 結果のMatrix4．．
	 */
	Matrix4 operator *= ( const Matrix4& M );

	/*===========================================================================*/
	/**
	 * (*=) 演算子オーバーロード．
	 * 
	 * @param [in]  s スカラー．
	 * @return 結果のMatrix4．
	 */
	Matrix4 operator *= ( float s );

	/*===========================================================================*/
	/**
	 * (/=)演算子オーバーロード．
	 * 
	 * @param [in]  s スカラー．
	 * @return 結果のMatrix4．
	 */
	Matrix4 operator /= ( float s );

public:
	/** @brief 行列成分 */
	float m[4][4];
};

/***  以下非メンバ関数 *******************************************************/

/*===========================================================================*/
/**
 * (+)演算子オーバーロード．
 * 
 * @param [in]  m1 Matrix4．
 * @param [in]  m2 Matrix4．
 * @return 結果のMatrix4．
 */
const Matrix4 operator + ( const Matrix4& m1, const Matrix4& m2 );

/*===========================================================================*/
/**
 * (-)演算子オーバーロード．
 * 
 * @param [in]  m1 Matrix4．
 * @param [in]  m2 Matrix4．
 * @return 結果のMatrix4．
 */
const Matrix4 operator - ( const Matrix4& m1, const Matrix4& m2 );

/*===========================================================================*/
/**
 * (*)演算子オーバーロード．
 * 
 * @param [in]  m1 Matrix4．
 * @param [in]  m2 Matrix4．
 * @return 結果のMatrix4．
 */
const Matrix4 operator * ( const Matrix4& m1, const Matrix4& m2 );

/*===========================================================================*/
/**
 * (*) 演算子オーバーロード．
 * 
 * @param [in]  M Matrix4．
 * @param [in]  s スカラー．
 * @return 結果のMatrix4．
 */
const Matrix4 operator * ( const Matrix4& m, const float s );

/*===========================================================================*/
/**
 * (*) 演算子オーバーロード．
 * 
 * @param [in]  s スカラー．
 * @param [in]  M Matrix4．
 * @return 結果のMatrix4．
 */
const Matrix4 operator * ( const float s, const Matrix4& m );

/*===========================================================================*/
/**
 * (/) 演算子オーバーロード．
 * 
 * @param [in]  M Matrix4．
 * @param [in]  s スカラー．
 * @return 結果のMatrix4．
 */
const Matrix4 operator / ( const Matrix4& m, const float s );

/*===========================================================================*/
/**
 * (==) 演算子オーバーロード．
 * 
 * @param [in]  m1 Matrix4．
 * @param [in]  m2 Matrix4．
 * @return 比較結果．
 */
bool  operator == ( const Matrix4& m1, const Matrix4& m2 );

/*===========================================================================*/
/**
 * (!=) 演算子オーバーロード．
 * 
 * @param [in]  m1 Matrix4．
 * @param [in]  m2 Matrix4．
 * @return 比較結果．
 */
bool  operator != ( const Matrix4& m1, const Matrix4& m2 );

} // namespace tglib

#endif

/********** End of File ******************************************************/
